﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using WssUtils;

/**
  TEST
  [EditorButton]
    private void OpenTest()
    {

        this.coroutineQueue = CoroutineQueue.Get(this);

        //测试命令
        this.PushCommand((cmd) =>
        {
            Debug.Log("windowA");
            var daily = UIManager.Instance.OpenWindow<UIDailyBoard>();
            daily.Init(() => cmd.CompleteCommand());
        });

          this.PushCommand((cmd) =>
        {
            Debug.Log("windowA");
            var daily = UIManager.Instance.OpenWindow<UIDailyBoard>();
            daily.Init(() => cmd.CompleteCommand());
        });

        this.DoCommand();
    }
*/

namespace WssUtils
{
    /// <summary>
    /// 携程队列  ver 1.0.0 
    /// 支持按顺序执行命令
    /// </summary>
    public class CoroutineQueue : SingletonMonoBehaviour<CoroutineQueue>
    {

        public static CoroutineQueue Global => Instance;

        /// <summary>
        /// 检测指令类
        /// </summary>
        public class CheckCommand
        {
            public CoroutineQueue windowQueue;
            internal bool isComplete = false;
            internal bool isBreak = false;
            private Action<CheckCommand> action;
            
            //加入一个用来分辨是否在队列中的弹窗标识
            public string Code;
            public CheckCommand(Action<CheckCommand> action, CoroutineQueue windowGroup,string code = "")
            {
                this.windowQueue = windowGroup;
                this.action = action;
                Code = code;
            }

            public void DoAction()
            {
                if (action == null)
                    this.Complete();
                else
                    action?.Invoke(this);
            }

            /// <summary>
            /// 使用 CoroutineQueue 执行一个携程命令
            /// </summary>
            /// <param name="routine"></param>
            public void StartCoroutine(IEnumerator routine)
            {
                this.windowQueue.StartCoroutine(routine);
            }

            /// <summary>
            /// 手动完成指令
            /// </summary>
            public void Complete()
            {
                isComplete = true;
            }

            /// <summary>
            /// 延迟完成指令
            /// </summary>
            public void DelayComplete(float time)
            {
                this.windowQueue.Invoke("Complete", time);
            }

            /// <summary>
            /// 强制中断后续命令的执行
            /// </summary>
            public void Break()
            {
                isComplete = true;
                isBreak = true;
            }
        }

        public Queue<CheckCommand> actionList = new Queue<CheckCommand>();

        /// <summary>
        /// 直接从GameObject 是否持有该对象，如果有就直接取得使用
        /// </summary>
        /// <param name="monoBehaviour"></param>
        /// <returns></returns>
        public static CoroutineQueue Get(MonoBehaviour monoBehaviour)
        {
            var queue = monoBehaviour.gameObject.GetComponent<CoroutineQueue>();
            if (queue == null)
            {
                queue = monoBehaviour.gameObject.AddComponent<CoroutineQueue>();
            }
            return queue;
        }

        public void Clear()
        {
            this.actionList.Clear();
        }

        private IEnumerator curCoroutine;

        /// <summary>
        /// 执行队列里的命令，直到全部完成
        /// </summary>
        public CoroutineQueue DoCommand()
        {
            curCoroutine = _DoCommand();
            StartCoroutine(curCoroutine);
            return this;
        }

        /// <summary>
        /// 推入需要执行的下一条命令
        /// </summary>
        /// <param name="act"></param>
        public CoroutineQueue Push(Action<CheckCommand> act,string code = "")
        {
            this.actionList.Enqueue(new CheckCommand(act, this,code));
            return this;
        }

        /// <summary>
        /// 推入多条需要按顺序执行的命令
        /// </summary>
        /// <param name="acts"></param>
        public CoroutineQueue Push(IList<Action<CheckCommand>> acts)
        {
            foreach (var act in acts)
            {
                this.Push(act);
            }
            return this;
        }


        /// <summary>
        /// 停止命令，并且清除所有队列
        /// </summary>
        public void Stop()
        {
            this.actionList.Clear();
            this.StopCoroutine(this.curCoroutine);
        }

        /// <summary>
        /// 暂停命令，暂时不执行后续命令
        /// </summary>
        public void Pause()
        {
            if (this.curCoroutine != null)
                this.StopCoroutine(this.curCoroutine);
        }

        /// <summary>
        /// 恢复命令，继续执行后续命令
        /// </summary>
        public void Resume()
        {
            if (this.curCoroutine != null)
                this.StartCoroutine(this.curCoroutine);
        }

        //执行链式命令 (使用携程等待命令完成)
        public IEnumerator _DoCommand()
        {
            while (true)
            {
                if (this.actionList.Count > 0)
                {
                    var cmd = this.actionList.Dequeue();
                    cmd.DoAction();
                    yield return new WaitUntil(() => cmd.isComplete);
                    yield return new WaitForEndOfFrame();//等待帧结束
                    if (cmd.isBreak)
                    {
                        this.actionList.Clear();
                        break;
                    }
                }
                else
                {
                    break;
                }
            }
            yield return null;
        }

    }


}
